class UserController < ApplicationController
  include ApplicationHelper
  
  # Everything protected is only available to logged in users
  before_filter :protect, :except => [ :login, :register, :activate ]
  before_filter :protect_for_volcom, :only => [ :list, :user_search, :create_user ]
  before_filter :protect_for_self_or_volcom, :only => [ :edit, :edit_skills, :show, :add_link, :remove_link ]
  
  # register a user for an account
  def register
    @title = 'Register'.t
    if param_posted?(:user)
      @user = User.new(params[:user])
      @user.created_by_volcom = false
      begin 
        if @user.save!
          flash[:notice] = "Your account with username %s has been created!"/@user.username 
          redirect_to :action => "activate"
          return
        end
      rescue ActiveRecord::RecordInvalid
        if @user.errors.on(:email)
          # see if there is an existing inactive user with this email
          existing = User.find_by_email(params[:user][:email])
          if existing && existing.activated_at.nil? && !existing.activation_code.nil?
            # resend activation email
            UserNotifier.deliver_signup_notification(existing)
            flash[:notice] = "Resending activation email to the existing e-mail address.".t
          end
        end
        @user.clear_password_view!
        render :action => 'register'
      end
    end
  end
  
  # activate a new user's account on receipt of the code
  def activate
    if logged_in?
      flash[:notice] = "Your account is already active!".t
      redirect_to :action => 'index'
    elsif params[:id] || (params[:user] && params[:user][:id])
      id = params[:id] || params[:user][:id]
      @user = User.find( :first, :conditions => [ "activation_code = ? AND activated_at IS NULL", id ] )    
      if @user and @user.activate!
        @user.login!(session)
        flash[:notice] = "Your account has been activated!".t 
        redirect_to :action => 'index'
      else
        flash[:notice] = "Unable to activate your account.  Did you enter the right code?".t 
      end
    else
      flash[:notice] = "Please check your email for the activation code!".t
    end
  end  

  # allow a volcom member to create and activate a new user from outside
  def create_user
    if param_posted?(:new_user)
      @new_user = User.new(params[:new_user])
      @new_user.created_by_volcom = true
      begin
        if @new_user.save! and @new_user.activate!
          flash[:notice] = "Account for username %s has been created."/@new_user.username
          redirect_to :action => 'edit', :id => @new_user.id
        end
      rescue ActiveRecord::RecordInvalid
        flash[:error] = "Problems with account creation."
        @new_user.clear_password_view!
      end
    end
  end

  # login a user  
  def login
    @title = 'Login'.t
    if request.get?
      if logged_in? 
        redirect_to :action => "index"
      end
      @user = User.new(:remember_me => remember_me_value)
    elsif param_posted?(:user)
      @user = User.new(params[:user])
      user = User.authenticate(@user.username, @user.password)
      if user
        user.login!(session)
        if @user.remember_me?
          user.remember!(cookies)
        else
          user.forget!(cookies)
        end
        flash[:notice] = "User %s logged in."/user.username
        redirect_to_requested_url
      else
        if @user
          @user.clear_password_view!
        end
        flash[:notice] = "Invalid username/password combination."
      end
    end
  end
  
  def logout
    User.logout!(session, cookies)
    flash[:notice] = "Logged out"
    redirect_to :action => "login"
  end
  
  # This is the profile page for each user
  def index
    @title = "Your Volunteer Page"
    @userskills = @user.get_all_skills
  end
  
  def show
    @user_to_show = User.find(params[:id])
    if @user_to_show && (get_user.is_volcom || get_user.is_otw)
      @title = "Volunteer Page for #{@user_to_show.username}"
      @userskills = @user_to_show.get_all_skills      
    elsif @user
      flash[:error] = 'You may not see the profiles of other users.'.t
      redirect_to :action => "index"
    else
      flash[:error] = 'No such user found.'.t
      redirect_to :action=> 'list'
    end
  end  
  
  # This lists all volunteers
  def list
    @title = "Volunteers List"
    @display_columns = User.content_columns.reject { |c| c.name =~ /(password|authorization|_at|salt|activ)/i }
    @display_data = User.display_list(params)
  end
  
  def destroy
    if params[:id]
      @user_to_destroy = User.find(params[:id])
      if request.delete? && @user_to_destroy && get_user != @user_to_destroy && get_user.is_volcom
        @user_to_destroy.destroy
        flash[:notice] = 'User %s deleted.' / @user_to_destroy.username
      else
        flash[:error] = 'You may not delete %s.' / @user_to_destroy.username
      end
    end
    redirect_to :action => 'list'
  end
  
  # This edits a volunteer - only accessible to self or volcom
  def edit
    @title = "Edit Profile"
    @user_to_edit = User.find_by_id( params[:id] )
    
    if param_posted?(:user_to_edit)
      #if user entered bad password, don't allow password change
      if params[:user_to_edit][:password] && !params[:user_to_edit][:password].blank?
        unless params[:user_to_edit][:current_password] && @user_to_edit.password_matches?(params[:user_to_edit][:current_password])
          @user_to_edit.clear_password_view!
          flash[:error] = "Password mismatch.".t
          redirect_to :action => "edit", :id => params[:id]
          return
        end
      end

      # Check for permissions being set
      if params[:user_to_edit][:is_volcom] or params[:user_to_edit][:is_otw] or params[:user_to_edit][:is_translator]
        if !get_user.is_volcom
          flash[:error] = "You must be a volcom member to edit those fields."
          redirect_to :action => "edit", :id => params[:id]
          return
        elsif get_user == @user_to_edit
          flash[:error] = "You may not change your own permissions."
          redirect_to :action => "edit", :id => params[:id]
          return
        else
          @user_to_edit.is_volcom = params[:user_to_edit][:is_volcom]
          @user_to_edit.is_otw = params[:user_to_edit][:is_otw]
          @user_to_edit.is_translator = params[:user_to_edit][:is_translator]
          @user_to_edit.save!
        end
      end
      
      # don't allow username change
      if params[:user_to_edit][:username]
        flash[:error] = "Username changes not allowed."
        redirect_to :action => "edit", :id => params[:id]
        return
      elsif @user_to_edit.update_attributes(params[:user_to_edit])
        flash[:notice] = "Profile information updated."
        redirect_to :action => "edit", :id => params[:id]
        return
      end
    else
      @user_to_edit.clear_password_view!
      @skills = Skill.find_all_skills
    end
  end
  
  # Add/remove skills to a user -- this should get changed eventually to AJAX updating
  def edit_skills
    if params[:id]
      @user_to_edit = User.find_by_id(params[:id])
      if @user_to_edit && (@user_to_edit == get_user || get_user.is_volcom)
        # okay!
        @skills = Skill.find_all_skills
        @skills.each do |skill|
          if skill_checked?(skill) && !@user_to_edit.has_skill(skill.id)
            @user_to_edit.add_skill(skill.id)
          elsif !skill_checked?(skill) && @user_to_edit.has_skill(skill.id)
            @user_to_edit.remove_skill(skill.id)
          end
        end
        
        # report what skills the person has been saved with
        @userskills = @user_to_edit.get_all_skills
        if @userskills && @userskills.length > 0
          message = "Saved #{@user_to_edit.username} with the following skills: "
          message += @userskills.map {|skill| skill.skillname}.sort.join(', ')
        else
          message = "#{@user_to_edit.username} has been saved with no skills."
        end
        flash[:notice] = message
        redirect_to :action => "edit", :id => @user_to_edit.id
      end
    end
  end
  
  # Add a link to a user profile
  def add_link
    if params[:id] && params[:url]
      @user_to_edit = User.find_by_id(params[:id])
      if @user_to_edit
        @user_to_edit.add_link(params[:url])
      end
    end   
  end
  
  # Remove a link from a user profile
  def remove_link
    if params[:id] && params[:url]
      @user_to_edit = User.find_by_id(params[:id])
      if @user_to_edit
        @user_to_edit.remove_link(params[:url])
      end
    end
  end
  
  # search for users with matching characteristics
  def user_search
    match_any = (params[:match_type] && params[:match_type] == "any")

    # full-text query matching
    query_hits = find_queried(params[:query], User, :match_any => match_any)
    
    # skill matching
    @skills_to_match = Skill.find_all_skills.select {|skill| skill_checked?(skill)}
    skill_hits = find_skilled(@skills_to_match, User, :match_any => match_any)
    
    # return only users who fit all criteria
    # return only jobs which fit all criteria
    data = find_union(:query => params[:query], :query_hits => query_hits,
                      :skills => @skills_to_match, :skill_hits => skill_hits,
                      :match_any => match_any)

    if data.nil?
      data = User.display_list(params)
    end
           
    unless params[:inactive]
      data = data & User.find_all_by_is_available(true)
    end
    
    @display_data = data
  end
  
  private
  
  # Protect an id-specific page from access except by self or volcom
  def protect_for_self_or_volcom
    user = get_user
    user_to_access = User.find_by_id( params[:id] )
    unless user && user_to_access && (user == user_to_access || user.is_volcom )
      protect_redirect("Only Volunteers Committee members may access other users' pages.", 
      {:controller => "user", :action => "edit", :id => get_user.id})
      return false
    end
  end
  
  
  # Redirect to the previously-requested URL post-login
  def redirect_to_requested_url
    redirect_url = session[:protected_page]
    if (redirect_url)
      session[:protected_page] = nil
      redirect_to redirect_url
    else
      redirect_to :action => "index"
    end
  end
  
  # Status of the remember_me checkbox
  def remember_me_value
    cookies[:remember_me] || "0"
  end
  
end
